<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2022/4/11
 * Time: 14:17
 */

namespace app\logic;


use app\common\lib\JwtToken;
use app\exception\IndexException;
use app\model\ai\AiCommandModel;
use app\model\consume\ConsumePointLogModel;
use app\model\plan\PromotionPlanModel;
use app\model\reward\RewardPlanModel;
use app\model\user\UserIncomeFlowModel;
use app\model\user\UserInviteRelationModel;
use app\model\user\UserLoginRecordModel;
use app\model\user\UserModel;
use app\model\user\UserPointFlowModel;
use app\model\user\UserPromotionOrderIncomeModel;
use support\Db;

abstract class BaseLogic
{

    public function __construct()
    {

    }

    protected static function getInstances($nameSpace)
    {
    }

    protected function unsetCommonFields($data, $extFields = [])
    {
        $commfields = ['created_at', 'update_at', 'adduser', 'isdel', 'status'];
        is_string($extFields) && $extFields = explode(',', $extFields);
        $unsetFields = array_merge($commfields, $extFields);

        if (isset($data[0]) && !empty($data)) {
            foreach ($data as &$val) {
                foreach ($unsetFields as $key) {
                    if (isset($val[$key])) {
                        unset($val[$key]);
                    }
                }
            }
        } else {
            foreach ($unsetFields as $key) {
                if (isset($data[$key])) {
                    unset($data[$key]);
                }
            }
        }

        return $data;
    }

    protected function loginData($user)
    {
        unset($user->userid);

        $user->login_time = time();

        $expireTime = 1000 * 86400;

        $user->expire_time = time() + $expireTime;

        $user->token = JwtToken::getInstance()->createToken($user->toArray(), $expireTime);

        $this->unsetCommonFields($user,['source_ip','expire_time','login_time','scene']);

        //登录记录
        UserLoginRecordModel::getInstance()->insertData($user);

        return $user;
    }

    /**
     * 线形和柱形图报表数据格式组装
     * @param $data
     * @param $targetFields
     * @param $xField
     * @param $types
     * @param $tooltips
     * @return array
     */
    public function assembleLineData($data, $targetFields, $xField, $types = [], $tooltips = [])
    {
        $returnData = [
            'categories' => [],
            'series' => [],
        ];
        foreach ($data as $k => $val) {
            $returnData['categories'][$k] = $val[$xField];
            $index = 0;
            foreach ($targetFields as $key => $field) {
                $returnData['series'][$key]['name'] = $field;
                $returnData['series'][$key]['type'] = isset($types[$key]) ? $types[$key] : 'bar';
                $returnData['series'][$key]['data'][$k] = $val[$key];
                $returnData['series'][$key]['yAxisIndex'] = $index;
                $index++;
            }
        }
        $returnData['series'] = array_values($returnData['series']);
        return $returnData;
    }

    public function randSortWhere($model, $where, $idKey, $cacheTime = 300)
    {
        $keyString = get_class($model);
        $keyString .= serialize($where);
        $keyString .= $idKey;
        $idStringKey = substr(md5($keyString), -16);

        $data = Cache::get($idStringKey);
        if (!$data) {
            $idField = strpos($idKey, '.') > 0 ? substr($idKey, strpos($idKey, '.')) : $idKey;
            $idAll = $model->getWhere($where)->orderBy($idField, 'desc')->pluck($idField)->toArray();
            shuffle($idAll);

            $query = $model->getWhere($where);
            $pageData = $model->buildPage($query);

            $data = [$idAll, $pageData];
            Cache::set($idStringKey, $data, $cacheTime);
        }

        list($idAll, $pageData) = $data;
        $pageData['pageNo'] = (int)request()->input('page', 1);
        $offset = ($pageData['pageNo'] - 1) * $pageData['pageSize'];
        $ids = array_slice($idAll, $offset, $pageData['pageSize']);

        $where = [];
        $where[] = [$idKey, 'in', $ids];

        $data = [$where, $ids, $pageData];

        return $data;
    }

    /**
     * 分页数据
     * @param $allData
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function buildPage($allData, $page = 1, $pageSize = 15)
    {
        $totalCount = count($allData);

        $inputPageNo = request() ? request()->input('page') : 0;
        $inputPageSize = request() ? request()->input('limit') : 0;
        if ($inputPageNo) {
            $page = (int)$inputPageNo;
        }
        if ($inputPageSize) {
            $pageSize = (int)$inputPageSize;
        }
        if ($page < 1) {
            $page = 1;
        }

        if ($pageSize < 1) {
            $pageSize = 15;
        }

        $data = [];
        $data['pageSize'] = $pageSize;
        $data['totalCount'] = $totalCount;
        $data['totalPage'] = ceil($totalCount / $pageSize);
        $data['totalPage'] = $data['totalPage'] > 0 ? $data['totalPage'] : 1;

        $data['pageNo'] = $page;

        $offset = ($data['pageNo'] - 1) * $data['pageSize'];

        $curData = array_slice($allData, $offset, $data['pageSize']);

        return [$curData, $data];
    }

    /**
     * 用户设置值map对象关系
     * @param $userSns
     * @param $key
     * @param $isKeyValue
     * @return array
     */
    public function getUserSetValueMap($userSns, $key = false, $isKeyValue=true)
    {
        $model = UserSetModel::getInstance();
        //多条用in
        if (is_array($userSns)) {
            $model = $model->getWhere([['user_sn', 'in', $userSns]]);
        } else {
            $model = $model->getWhere(['user_sn' => $userSns]);
        }
        if (!empty($key)) {
            $model = $model->where(['key' => $key]);
        }
        $userSetData = $model->select(['key', 'value', 'user_sn', 'expiretime'])->get();
        $userSetMap = [];

        foreach ($userSetData as $val) {
            if ($val['value'] > 0 && $val['expiretime'] > 0 && time() > $val['expiretime']) {
                $val['value'] = 0;
            }

            $userSetMap[$val['user_sn']][$val['key']]['value'] = $val['value'];
            $userSetMap[$val['user_sn']][$val['key']]['expiretime'] = $val['expiretime'];
        }

        $returnSetMap = [];
        $userSnData = is_array($userSns) ? $userSns : explode(',',$userSns);
        foreach ($userSnData as $userSn){
            $setData = isset($userSetMap[$userSn]) ? $userSetMap[$userSn] : [];
            foreach (Constant::USER_SET_MAP as $setKey=>$setValue){
                $set = [];
                if(!isset($setData[$setKey])){
                    $set['value'] = $setValue;
                    $set['expiretime'] = 0;
                }else{
                    $set['value'] = $setData[$setKey]['value'];
                    $set['expiretime'] = $setData[$setKey]['expiretime'];
                }

                if($isKeyValue){
                    $returnSetMap[$userSn][$setKey] = $set['value'];
                }else{
                    $returnSetMap[$userSn][$setKey] = $set;
                }
            }
        }

        return $returnSetMap;
    }

    /**
     * 保存远程文件到本地服务器
     * @desc 临时目录，上存到oss、七牛后记得删除文件
     * @param $url --远程文件链接
     * @return string
     * @throws \Exception
     */
    protected function saveTempFile($url, $suffix = '')
    {
        $link = strstr($url, '?', true);
        if (empty($suffix)) {
            $suffix = substr($link, strrpos($link, '.') + 1) ?? 'pdf';
        }
        list ($t1, $t2) = explode(' ', microtime());
        $fileName = sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000) . '_' . random_int(1, 999999) . '.' . $suffix;
        //文件保存绝对路径
        $path = App()->storagePath() . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR;
        if (!is_dir($path)) {
            @mkdir($path, 0777, true);
        }
        $path = $path . $fileName;
        $content = file_get_contents($url);
        $fp2 = @fopen($path, "a");
        fwrite($fp2, $content);
        fclose($fp2);
        return $path;
    }

    /**
     * 数组分组
     * @param  [type] $arr [二维数组]
     * @param  [type] $key [键名]
     * @return [type]      [新的二维数组]
     */
    public function arrayGroup($arr, $key)
    {
        $grouped = [];
        foreach ($arr as $value) {
            $grouped[$value[$key]][] = $value;
        }
        if (func_num_args() > 2) {
            $args = func_get_args();
            foreach ($grouped as $key => $value) {
                $parms = array_merge($value, array_slice($args, 2, func_num_args()));
                $grouped[$key] = call_user_func_array('arrayGroup', $parms);
            }
        }
        return $grouped;
    }

    /**
     * 获取远程图片的宽高
     * @param $url
     * @return array
     */
    public function getImageHeightAndWidth($url)
    {
        $imageHeight = 0;
        $imageWidth  = 0;
        $isFind      = false;
        $ossLinkArr  = [
            'http://hi-static.lovewidget.cn',
            'https://hi-static.lovewidget.cn',
            'http://bxwidget.oss-cn-shanghai.aliyuncs.com',
            'https://bxwidget.oss-cn-shanghai.aliyuncs.com',
            'http://biaoqingbao-vision.oss-cn-shanghai.aliyuncs.com'
        ];
        foreach ($ossLinkArr as $v) {
            $pos   = strpos($url, $v);
            if ($pos !== false) {
                $isFind = true;
                break;
            }
        }
        if (!empty($url)) {
            if ($isFind) {
                $imageInfo = file_get_contents($url . '?x-oss-process=image/info');
                $imageInfo   = json_decode($imageInfo, true);
                $imageHeight = $imageInfo['ImageHeight']['value'] ?? 0;
                $imageWidth  = $imageInfo['ImageWidth']['value']  ?? 0;
            } else {
                $imageInfo   = getimagesize($url);
                $imageWidth  = $imageInfo[0] ?? 0;
                $imageHeight = $imageInfo[1] ?? 0;
            }
        }
        return [$imageWidth, $imageHeight];
    }

    /**
     * 跟数据列表对应id获取关系表数据---一对一 key映射模式
     * @param $model
     * @param $data
     * @param $keyIdField
     * @param $idField
     * @param array $extParam['field','where']
     * @return array
     * @throws \think\Exception
     */
    public function getListMapById($model,$data,$keyIdField,$idField,$extParam=[])
    {
        if(empty($data) || empty($model)){
            return [];
        }

        $ids = array_column($data, $keyIdField);
        $ids && $ids =  array_unique($ids);

        $fields = $extParam['field']??'*';
        $extWhere = $extParam['where']??[];

        if($fields!='*'){
            if(is_string($fields)){
                $fields = explode(',', $fields);
            }
            array_unshift($fields,$idField);
            $fields = array_unique($fields);
        }

        $listData = $model->getWhere($extWhere)->whereIn($idField,$ids)->select($fields)->get()->toArray();

        if($listData){
            return array_column($listData,null,$idField);
        }

        return [];
    }

    /**
     * 跟数据列表对应id获取关系表数据---一对多模式
     * @param $model
     * @param $data
     * @param $keyIdField
     * @param $idField
     * @param array $extParam['field','where','order'=>['sort desc','id asc']]
     * @return array
     * @throws \think\Exception
     */
    public function getListAllMapById($model,$data,$keyIdField,$idField,$extParam=[])
    {
        if(empty($data) || empty($model)){
            return [];
        }

        $ids = array_column($data, $keyIdField);
        $ids && $ids =  array_unique($ids);

        $fields = $extParam['field']??'*';
        $extWhere = $extParam['where']??[];
        $orders = $extParam['order']??[];

        if($fields!='*'){
            if(is_string($fields)){
                $fields = explode(',', $fields);
            }
            array_unshift($fields,$idField);
            $fields = array_unique($fields);
        }

        $query = $model->getWhere($extWhere)->whereIn($idField,$ids);
        if($orders){
            foreach($orders as $order){
                $orderArr = explode(' ',$order);
                $query = $query->orderBy($orderArr[0],$orderArr[1]);
            }
        }
        $listData = $query->select($fields)->get()->toArray();

        $returnData = [];
        if($listData){
            foreach ($listData as $val){
                $returnData[$val[$idField]][] = $val;
            }
        }

        return $returnData;
    }

    /**
     * 跟数据列表对应id获取关系表数据---多对多模式
     * @param $model
     * @param $relatedModel
     * @param $data
     * @param $keyIdField
     * @param $idField
     * @param array $extParam['field','where','order'=>['sort desc','id asc'],'relatedKey'=>['keyIdField','idField']
     * @return array
     * @throws \think\Exception
     */
    public function getListAllMapDataById($model,$relatedModel,$data,$keyIdField,$idField,$extParam=[])
    {
        if(empty($data) || empty($model) || empty($relatedModel)){
            return [];
        }
        $keyIdFieldKey = $keyIdField;
        $idFieldKey = $idField;
        if(!empty($extParam['relatedKey'])){
            $keyIdFieldKey = $extParam['relatedKey'][0];
            $idFieldKey = $extParam['relatedKey'][1];
        }


        $ids = array_column($data, $keyIdField);
        $ids && $ids =  array_unique($ids);

        $fields = $extParam['field']??'*';
        $extWhere = $extParam['where']??[];
        $orders = $extParam['order']??[];

        if($fields!='*'){
            if(is_string($fields)){
                $fields = explode(',', $fields);
            }
            array_unshift($fields,'b.'.$idField);
            array_unshift($fields,'b.'.$keyIdFieldKey);
            $fields = array_unique($fields);
        }

        $query = $model->setTable($model->getTable().' as a')
            ->join($relatedModel->getTable().' as b','a.'.$idFieldKey,'=','b.'.$idField)
            ->where($extWhere)->whereIn($keyIdFieldKey,$ids);

        if($orders){
            foreach($orders as $order){
                $orderArr = explode(' ',$order);
                $query = $query->orderBy($orderArr[0],$orderArr[1]);
            }
        }
        $listData = $query->select($fields)->get()->toArray();

        $returnData = [];
        if($listData){
            foreach ($listData as $val){
                $returnData[$val[$keyIdField]][] = $val;
            }
        }

        return $returnData;
    }

    /**
     * 跟数据对应id获取关系表数据,获取详情数据
     * @param $model
     * @param $data
     * @param $keyIdField
     * @param $idField
     * @param array $extParam
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getDetailDataById($model,$data,$keyIdField,$idField,$extParam=[])
    {
        if(empty($data) || !isset($data[$keyIdField])){
            return [];
        }

        $id = $data[$keyIdField];

        $fields = $extParam['field']??'*';
        $extWhere = $extParam['where']??[];

        if($fields!='*'){
            if(is_string($fields)){
                $fields = explode(',', $fields);
            }
            array_unshift($fields,$idField);
            $fields = array_unique($fields);
        }

        $detailData =  $model->getWhere($extWhere)->where($idField,$id)->select($fields)->first();

        if($detailData){
            return $detailData->toArray();
        }

        return [];
    }

    /**
     * 自动创建表和插入表的数据
     * @param $param
     * @return int
     */
    public function autoCreateTableAndInsertData($param)
    {
        $tableName = $param['table'];
        $mysql = 'SELECT COUNT(*) as count FROM information_schema.TABLES WHERE table_name =\''.$tableName.'\';';
        $result = Db::select($mysql);

        //判断是否存在该事件的表
        if(isset($result[0]) && $result[0]->count>0){
            //todo 1 存在表
            $mysql = "desc `$tableName`";
            $result = Db::select($mysql);
            $fieldMap = array_column($result, 'Type', 'Field');

            //判断表的字段是否存在或者长度是否满足，不满足添加字段或者修改
            $mysqlChangeArr = [];
            $insert = [];
            $update = [];
            foreach($param['attributes'] as $field=>&$value){
                $field = strtolower($field);
                $value = is_array($value) ? json_encode($value,256) : ($value??'');
                $length = mb_strlen(((string)$value));
                if(isset($fieldMap[$field]) && strpos($fieldMap[$field],'var')!==false){
                    preg_match('/\d+/',$fieldMap[$field],$match);
                    $varLen = $match[0];

                    if(isset($fieldMap[$field]) && $length>$varLen){
                        $mysqlChangeArr[] = 'ALTER TABLE `video_db`.`'.$tableName.'` MODIFY COLUMN `'.$field.'` varchar('.$length.')
                        CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT \'\';';
                    }
                }elseif(!isset($fieldMap[$field])){
                    $length = $length>50 ? $length : 50;
                    $mysqlChangeArr[] = 'ALTER TABLE `video_db`.`'.$tableName.'` ADD COLUMN `'.$field.'` varchar('.$length.') NOT NULL DEFAULT \'\' ;';
                }

                if(!empty($param['update_fields']) && in_array($field,$param['update_fields'])){
                    $update[$field] = $value;
                }else{
                    $insert[$field] = $value;
                }
            }
            foreach($mysqlChangeArr as $mysqlStr){
                Db::select($mysqlStr);
            }

            $insert['created_at'] = date('Y-m-d H:i:s');
            if($update){
                $insertId = Db::table($tableName)->updateOrInsert($update,$insert);
            }else{
                $insertId = Db::table($tableName)->insertGetId($insert);
            }
        }else{
            //todo 2 不存在表
            $insert = [];
            $id = ($param['keyid']??'id');
            $mysqlStr = 'CREATE TABLE `'.$tableName.'` (';
            $mysqlStr .= '`'.$id.'` int(11) unsigned NOT NULL AUTO_INCREMENT,';

            foreach($param['attributes'] as $field=>&$value){
                $field = strtolower($field);
                $value = is_array($value) ? json_encode($value,256) : ($value??'');
                $insert[$field] = $value;

                $length = mb_strlen(((string)$value));
                $length = $length>50 ? $length : 50;
                $mysqlStr .= ' `'.$field.'` varchar('.$length.') NOT NULL DEFAULT \'\',';
            }

            $mysqlStr .= '`created_at` datetime NOT NULL COMMENT \'添加时间\',';
            $mysqlStr .= 'PRIMARY KEY (`'.$id.'`) USING BTREE';
            $mysqlStr .= ') ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;';

            Db::select($mysqlStr);

            $insert['created_at'] = date('Y-m-d H:i:s');
            $insertId = Db::table($tableName)->insertGetId($insert);
        }

        return $insertId;
    }

    /**
     * 二维数组根据某个字段排序
     * @param  array  $array       --要排序的数组
     * @param  string $SortField   --要排序的字段
     * @param  string $sort        --排序类型  asc desc
     * @return array               --排序后的数组
     */
    function arraySort(array $array, string $SortField, string $sort = 'asc')
    {
        $sort = $sort == 'asc' ? SORT_ASC : SORT_DESC;
        $fieldValue = array_column($array, $SortField);
        array_multisort($fieldValue, $sort, $array);
        return $array;
    }

    /**
     * 二维数组根据多字段排序
     * @param  array   $array       --要排序的二维数组
     * @param  array   $field       --排序的字段数组  ['date' => SORT_DESC, 'new_user_num' => SORT_DESC]
     * @return array
     */
    function sortByCols(array $array, array $field) {
        $sortArr   = [];
        $sortRule  = '';
        foreach ($field as $field => $sortWay) {
            foreach ($array as $k => $v) {
                $sortArr[$field][$k] = $v[$field];
            }
            $sortRule .= '$sortArr["' . $field . '"],' . $sortWay . ',';
        }
        if (empty($sortArr) || empty($sortRule)) {
            return $array;
        }
        eval('array_multisort(' . $sortRule . ' $array);');
        return $array;
    }

    /**
     * 填充达人收益
     * @param $param
     * @param $isImitate
     * @return mixed
     * @throws IndexException
     */
    public function fillPayIncomeData($param,$isImitate=false)
    {
        //短剧信息
        $skitData = $param['skit_data'];

        //达人奖励比例
        $user = UserModel::getInstance()->getWhere(['user_sn'=>$param['user_sn']])->first(['agent_level','reward_plan_id']);
        $levelRewardsFirst=false;
        if($user['reward_plan_id']>0){
            $levelRewardsFirst = RewardPlanModel::getInstance()->find($user['reward_plan_id']);
        }
        if($levelRewardsFirst==false){
            $levelRewardsFirst = RewardPlanModel::getInstance()->find(1);
        }
        //获取用户代理级别
        $agentLevel = UserModel::getInstance()->getUserAgentVip($param['user_sn'],$param['date']);
        if($param['promotion_type']==5){
            $userTalentRate = json_decode($levelRewardsFirst['v'.$agentLevel.'_plan_data2'],true)['talent_rate'];
        }else{
            $userTalentRate = json_decode($levelRewardsFirst['v'.$agentLevel.'_plan_data'],true)['talent_rate'];
        }

        //奖励比例
        $promotionRate = 0;
        if($param['platform']==1){
            //获取任务详情信息
            $param['anchor_title'] = DB::table('live_douyin_promotion_task_detail')->where(['task_id'=>$param['taskid']])->value('anchor_title');
            $paymentAllocateRatio = DB::table('live_douyin_promotion_task_detail')->where(['task_id'=>$param['taskid']])->value('payment_allocate_ratio');
            //计划比例
            $promotionRate = round($paymentAllocateRatio/100/11*10,3);
            $promotionRates = explode('.',(string)$promotionRate);
            $promotionRates[1] = $promotionRates[1]??'0';
            $promotionRate = (float)($promotionRates[0].'.'.substr($promotionRates[1],0,1));
        }
        $officialRate = (float)($userTalentRate-$promotionRate);
        $officialRate = $officialRate>0 ? $officialRate : 0.0;

        $payAmount = $param['amount'];
        $refundAmount = $param['refund_amount']??0;
        $getAmount = ($payAmount-$refundAmount);

        //填充短剧充值收益
        $incomeAmountFloat = round(abs($getAmount)*$userTalentRate/100,8);
        $incomeAmount = explode('.',(string)$incomeAmountFloat);
        $incomeAmount[1] = $incomeAmount[1]??'00';
        $incomeAmount = (float)($incomeAmount[0].'.'.substr($incomeAmount[1],0,2));

        $promotionReward = 0;
        if($param['platform']==1){
            $promotionRewardFloat = round(abs($getAmount)*$promotionRate/100,8);
            $promotionReward = explode('.',(string)$promotionRewardFloat);
            $promotionReward[1] = $promotionReward[1]??'00';
            $promotionReward = (float)($promotionReward[0].'.'.substr($promotionReward[1],0,2));
            $promotionReward = (float)($promotionRewardFloat<0.01 && $promotionRewardFloat>0 ? 0.01 : $promotionReward);
        }

        $officialRewardFloat = (float)($incomeAmountFloat-$promotionReward);
        $officialReward = explode('.',(string)$officialRewardFloat);
        $officialReward[1] = $officialReward[1]??'00';
        $officialReward = (float)($officialReward[0].'.'.substr($officialReward[1],0,2));
        $officialReward = (float)($officialRewardFloat<0.01 && $officialRewardFloat>0 ? 0.01 : $officialReward);

        $using = $getAmount<0 ? '-':'';
        $skitIncomeData = [
            'user_sn'=>$param['user_sn'],
            'income_amount'=>$using.$incomeAmount,
            'pay_amount'=>$payAmount,
            'level_type'=>0,
            'income_source_user_sn'=>0,
            'pay_time'=>$param['date'],
            'source_table'=>$param['source_table']??'',
            'source_id'=>$param['source_id']??0,
            'platform'=>$param['platform']??1,
            //'business_logo'=>$business['logo']??'',
            'business_name'=>$param['business_name']??'',
            'status'=>$param['status']??0,
            'createtime'=>date('Y-m-d H:i:s'),
            'updatetime'=>date('Y-m-d H:i:s'),
            'skit_title'=>$skitData['title']??'',
            'main_image'=>$skitData['main_image']??'',
            'skit_sn'=>$skitData['skit_sn']??'',
            'author'=>$param['author']??'',
            'anchor_title'=>$param['anchor_title']??'',
            'refund_amount'=>$refundAmount,
            'videolink'=>$param['videolink']??'',
            'official_reward'=>$using.$officialReward,
            'promotion_reward'=>$using.$promotionReward,
            'taskid'=>$param['taskid']??'',
            'videoid'=>$param['videoid']??'',
            'reward_rate'=>$userTalentRate,
            'promotion_rate'=>$promotionRate,
            'official_rate'=>$officialRate,
            'douyin_id'=>$param['douyin_id']??'',
            'app_id'=>$param['app_id'],
            'agent_level'=>$agentLevel,
            'reward_plan_id'=>$levelRewardsFirst['reward_plan_id']??1,
            'income_type'=>$param['income_type']??1,
            'promotion_type'=>$param['promotion_type']??1,
        ];

        //如果补贴小于0 ，则是退款，直接结算扣掉流水金额
        if($skitIncomeData['official_reward']<0){
            $skitIncomeData['status'] = 2;
            $skitIncomeData['settle_time'] = $param['date'];
        }

        $userIncomeFlow = [
            'user_sn'=>$param['user_sn'],
            'amount'=>$skitIncomeData['official_reward'],
            'type'=>1,
            'status'=>$skitIncomeData['status'],
            'source_table'=>'live_user_skit_order_income',
            'createtime'=>date('Y-m-d H:i:s'),
            'income_date'=>$skitIncomeData['pay_time'],
        ];
        if($skitIncomeData['official_reward']<0){
            $userIncomeFlow['status'] = 2;
            $userIncomeFlow['settle_time'] = $param['date'];
        }

        //如果是模拟数据，直接保存，不往下走了
        if($isImitate===true){
            unset($skitIncomeData['createtime']);
            $skitIncomeData['unikey'] = $param['unikey'];
            $this->autoCreateTableAndInsertData([
                'table'=>'live_imitate_skit_order',
                'attributes'=>$skitIncomeData,
                'update_fields'=>['unikey'],
                'keyid'=>'imitate_skit_order_id',
            ]);

            return true;
        }

        //真实数据
        try{
            Db::connection('mysql')->beginTransaction();
            $uniValues = [
                'user_sn'=>$param['user_sn'],
                'source_table'=>$skitIncomeData['source_table'],
                'source_id'=>$skitIncomeData['source_id'],
                'income_type'=>$param['income_type'],
                'promotion_type'=>$skitIncomeData['promotion_type'],
            ];
            $count = UserSkitOrderIncome::getInstance()->getWhere($uniValues)->count();
            if($count==false){
                UserSkitOrderIncome::getInstance()->insert($skitIncomeData);
            }

            $skitOrderIncomeId = UserSkitOrderIncome::getInstance()->getWhere($uniValues)->value('skit_order_incomeid');
            $uniValues = [
                'source_table'=>'live_user_skit_order_income',
                'sourceid'=>$skitOrderIncomeId,
            ];
            $count = UserIncomeFlowe::getInstance()->getWhere($uniValues)->count();
            if($count==false){
                $userIncomeFlow['sourceid'] = $skitOrderIncomeId;
                UserIncomeFlowe::getInstance()->insert($userIncomeFlow);
            }

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }catch (\Exception $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }catch (\Throwable $e){
            Db::connection('mysql')->rollBack();
            throw $e;
        }

        //todo 邀请奖励
        $this->fillAgentIncomeData($param['user_sn'],$skitOrderIncomeId);

        return $skitOrderIncomeId;
    }

    /**
     * 填充分销收益
     * @param $userSn
     * @param $orderIncomeId
     * @return bool
     * @throws IndexException
     * @throws \Throwable
     */
    protected function fillAgentIncomeData($userSn,$orderIncomeId)
    {
        $user = UserModel::getInstance()->getWhere(['user_sn'=>$userSn])->first(['user_sn','reward_plan_id','parentid','user_role']);
        //达人不存在，或者没有上级，或者是渠道商，就不做分销收益了
        if($user==false || $user['parentid']==0 || $user['user_role']>0){
            return false;
        }

        $skitOrderIncome = UserPromotionOrderIncomeModel::getInstance()->find($orderIncomeId);
        if($skitOrderIncome==false){
            return false;
        }

        $dateTime = date('Y-m-d',strtotime($skitOrderIncome['pay_time']));
        $agentLevel = UserModel::getInstance()->getUserAgentVip($userSn,$dateTime);

        $defaultLevelRewardsFirst = RewardPlanModel::getInstance()->find(1);

        $userMap = UserInviteRelationModel::getInstance()->getWhere(['invite_user_sn'=>$user['user_sn'],['level','=',1]])->orderBy('level','asc')->pluck('level','user_sn');
        $key = '';
        foreach($userMap as $userSn=>$level){
            $userRow = UserModel::getInstance()->getWhere(['user_sn'=>$userSn,'isdel'=>0])->first(['user_sn','reward_plan_id','parentid','user_role']);
            if($userRow==false){
                break;
            }

            //用户代理级别
            $userRowLevel = UserModel::getInstance()->getUserAgentVip($userSn,$dateTime);

            //todo 奖励方案
            $levelRewardsFirst=false;
            if($userRow['reward_plan_id']>0){
                $levelRewardsFirst = RewardPlanModel::getInstance()->find($userRow['reward_plan_id']);
            }
            if($levelRewardsFirst==false){
                $levelRewardsFirst = $defaultLevelRewardsFirst;
            }
            $levelReward = json_decode($levelRewardsFirst['v'.$agentLevel.'_plan_data'],true);

            //todo 获取奖励比例
            if($level==1){
                //直推
                $key = 'level'.$level.'_v'.$userRowLevel;
                if(empty($levelReward[$key])){
                    continue;
                }
            }elseif($level==2){
                //间推
                $key = 'level'.$level.'_v'.$userRowLevel.'_'.$key;
                if(empty($levelReward[$key])){
                    continue;
                }
            }

            $rewardRate = $levelReward[$key];
            $getAmount = ($skitOrderIncome['pay_amount']-$skitOrderIncome['refund_amount']);
            $incomeAmountFloat = round(abs($getAmount)*$rewardRate/100,8);
            $incomeAmount = explode('.',(string)$incomeAmountFloat);
            $incomeAmount[1] = $incomeAmount[1]??'00';
            $incomeAmount = (float)($incomeAmount[0].'.'.substr($incomeAmount[1],0,2));
            $incomeAmount = $incomeAmountFloat<0.01 && $incomeAmountFloat>0 ? 0.01 : $incomeAmount;

            $using = $getAmount<0 ? '-':'';
            $skitIncomeData = [
                'user_sn'=>$userSn,
                'income_amount'=>$using.$incomeAmount,
                'pay_amount'=>$skitOrderIncome['pay_amount'],
                'level_type'=>$level,
                'income_source_user_sn'=>$user['user_sn'],
                'pay_time'=>$skitOrderIncome['pay_time'],
                'source_table'=>$skitOrderIncome['source_table'],
                'source_id'=>$skitOrderIncome['source_id'],
                'platform'=>$skitOrderIncome['platform'],
                //'business_logo'=>$skitOrderIncome['business_logo'],
                'business_name'=>$skitOrderIncome['business_name'],
                'status'=>$skitOrderIncome['status'],

                'title'=>$skitOrderIncome['title'],
                'main_image'=>$skitOrderIncome['main_image'],
                'novel_sn'=>$skitOrderIncome['novel_sn'],
                'author'=>$skitOrderIncome['author']??'',
                'anchor_title'=>$skitOrderIncome['anchor_title'],
                'refund_amount'=>$skitOrderIncome['refund_amount'],
                'videolink'=>$skitOrderIncome['videolink'],
                'official_reward'=>$using.$incomeAmount,
                'taskid'=>$skitOrderIncome['taskid'],
                'videoid'=>$skitOrderIncome['videoid'],
                'reward_rate'=>$rewardRate,
                'douyin_id'=>$skitOrderIncome['douyin_id'],
                'app_id'=>$skitOrderIncome['app_id'],
                'agent_level'=>$userRowLevel,
                'reward_plan_id'=>$levelRewardsFirst['reward_plan_id']??1,
                'income_type'=>$skitOrderIncome['income_type'],
            ];
            !empty($skitOrderIncome['settle_time']) && $skitIncomeData['settle_time'] = $skitOrderIncome['settle_time'];

            //如果平台补贴小于0，则是退款，直接结算扣掉流水金额
            if($skitIncomeData['official_reward']<0){
                $skitIncomeData['status'] = 2;
                $skitIncomeData['settle_time'] = $skitOrderIncome['pay_time'];
            }
            $userIncomeFlow = [
                'user_sn'=>$userSn,
                'amount'=>$using.$incomeAmount,
                'type'=>1,
                'status'=>$skitOrderIncome['status'],
                'income_source_user_sn'=>$user['user_sn'],
                'income_date'=>$skitOrderIncome['pay_time'],
            ];
            !empty($skitIncomeData['settle_time']) && $userIncomeFlow['settle_time'] = $skitIncomeData['settle_time'];

            if($skitIncomeData['official_reward']<0){
                $userIncomeFlow['status'] = 2;
                $userIncomeFlow['settle_time'] = $skitOrderIncome['pay_time'];
            }
            try{
                Db::connection('mysql')->beginTransaction();
                $uniValue = [
                    'user_sn'=>$userSn,
                    'source_table'=>$skitOrderIncome['source_table'],
                    'source_id'=>$skitOrderIncome['source_id'],
                    'income_type'=>$skitOrderIncome['income_type'],
                ];
                $count = UserPromotionOrderIncomeModel::getInstance()->getWhere($uniValue)->count();
                if($count==false){
                    UserPromotionOrderIncomeModel::getInstance()->insert($skitIncomeData);
                }

                $orderIncomeId = UserPromotionOrderIncomeModel::getInstance()->getWhere($uniValue)->value('id');
                $uniValue = [
                    'source_table'=>UserPromotionOrderIncomeModel::getInstance()->getTable(),
                    'sourceid'=>$orderIncomeId,
                ];
                $count = UserIncomeFlowModel::getInstance()->getWhere($uniValue)->count();
                if($count==false){
                    $userIncomeFlow['source_table'] = UserPromotionOrderIncomeModel::getInstance()->getTable();
                    $userIncomeFlow['sourceid'] = $orderIncomeId;
                    UserIncomeFlowModel::getInstance()->insert($userIncomeFlow);
                }

                Db::connection('mysql')->commit();

            }catch (\Throwable $e){
                Db::connection('mysql')->rollBack();
                throw $e;
            }

            //如果没有上级，或者是渠道商，就不往下分销了，直接跳出
            if($userRow['parentid']==0 || $userRow['user_role']>0){
                break;
            }
        }

        return true;
    }

    public function consumePoint($param)
    {
        $user = $this->checkIsVip();
        $vipPointNums = 0;
        if($user['is_vip']==1){
            $vipPointNums = (int) UserPointFlowModel::getInstance()->getWhere(['user_sn'=>request()->curUserId,'type'=>1, ['created_at','>=',date('Y-m-d 00:00:00')]])->sum('nums');
        }elseif($user['is_vip']==2){
            $vipPointNums1 = (int) UserPointFlowModel::getInstance()->getWhere(['user_sn'=>request()->curUserId,'type'=>3,'way'=>2])->sum('nums');
            $vipPointNums2 = (int) UserPointFlowModel::getInstance()->getWhere(['user_sn'=>request()->curUserId,'type'=>3,'way'=>1, ['expired_time','>=',date('Y-m-d H:i:s')]])->sum('nums');
            $vipPointNums = round($vipPointNums2 - abs($vipPointNums1));
            $vipPointNums<0 && $vipPointNums = 0;
        }

        $buyPointNums = (int) UserPointFlowModel::getInstance()->getWhere(['user_sn'=>request()->curUserId,'type'=>2])->sum('nums');
        $consumePoint = $param['consume_point']??0;
        empty($consumePoint) && $consumePoint = (int) config('param.consume_point',40);

        if(empty($vipPointNums) && empty($buyPointNums)){
            throw new IndexException(3000,'点数不足,请充值');
        }

        $consumeVipPoint = 0;
        $consumeBuyPoint = 0;
        $balanceVipPoint = 0;
        $balanceBuyPoint = 0;
        if($vipPointNums>=$consumePoint){
            $consumeVipPoint = $consumePoint;
            $balanceVipPoint = round($vipPointNums-$consumePoint);
        }else{
            $diffNums = round($consumePoint-$vipPointNums);
            if($buyPointNums>=$diffNums){
                if($vipPointNums>0){
                    $consumeVipPoint = $vipPointNums;
                }
                $balanceBuyPoint = round($buyPointNums-$diffNums);
                $consumeBuyPoint = $diffNums;
            }else{
                throw new IndexException(3000,'点数不足,请充值');
            }
        }

        $data = [];
        $data['consume_vip_point'] = $consumeVipPoint;
        $data['consume_buy_point'] = $consumeBuyPoint;

        $data['balance_vip_point'] = $balanceVipPoint;
        $data['balance_buy_point'] = $balanceBuyPoint;
        $data['consume_point'] = $consumePoint;
        $data['is_vip'] = $user['is_vip'];

        return $data;
    }

    public function checkIsVip($user=false)
    {
        if($user==false){
            $user = UserModel::getInstance()->getWhere(['user_sn'=>request()->curUserId])->first();
        }
        $isVip = $user['is_vip'];
        $expireTime = 0;
        !empty($user['vip_expire_time']) && $expireTime = strtotime($user['vip_expire_time']);
        if($user['is_vip']>0 && $expireTime>0 && ($expireTime-time())>(86400*365*10)){
            //永久会员
            $user['is_vip']=$isVip>0 ? $isVip : 1;
        }elseif($user['is_vip']>0 && $expireTime>0 && $expireTime>time()){
            $user['is_vip']=$isVip>0 ? $isVip : 1;
        }else{
            $user['is_vip']=0;
        }

        return $user;
    }

    public function insertConsumePoint($consumePoint,$param,$type=1)
    {
        $pointData = $this->consumePoint(['consume_point'=>$consumePoint]);

        //todo 3 插入用户消费记录
        $insertLog = [
            'user_sn'      => request()->curUserId,
            'point'        => $pointData['consume_point'],
            'novel_sn'     => $param['novel_sn']??'0',
            'chapterid'    => $param['chapterid']??'0',
            'planid'       => $param['planid']??'0',
            'source_table' => $param['source_table']??'',
            'sourceid'     => $param['sourceid']??'0',
            'plan_type'     => $type,
            'articleid'     => $param['articleid']??'0',
            'videoid'     => $param['videoid']??'0',
        ];
        $logId     = ConsumePointLogModel::getInstance()->insertGetId($insertLog);

        //todo 4 插入用户消费流水
        if ($pointData['consume_vip_point'] > 0) {
            $insert = [
                'user_sn'      => request()->curUserId,
                'nums'         => -$pointData['consume_vip_point'],
                'sourceid'     => $logId,
                'source_table' => ConsumePointLogModel::getInstance()->getTable(),
                'type'         => $pointData['is_vip']==2 ? 3 : 1,
                'way'          => 2,
            ];
            UserPointFlowModel::getInstance()->insert($insert);
        }

        if ($pointData['consume_buy_point'] > 0) {
            $insert = [
                'user_sn'      => request()->curUserId,
                'nums'         => -$pointData['consume_buy_point'],
                'sourceid'     => $logId,
                'source_table' => ConsumePointLogModel::getInstance()->getTable(),
                'type'         => 2,
                'way'          => 2,
            ];
            UserPointFlowModel::getInstance()->insert($insert);
        }

        return true;
    }
}
